using System.Collections.Generic;
using NUnit.Framework;
using ValidationFramework;

namespace ExampleLibraryCSharp.PropertyValidationManagerExamples
{
	public class CustomClassExample
	{
		#region Example
		public class Person
		{
			#region Fields

			private readonly PropertyValidationManager propertyValidationManager;

			#endregion

			#region Constructors

			public Person()
			{
				propertyValidationManager = new PropertyValidationManager(this);
			}

			#endregion

			#region Properties

			/// <summary>
			/// Gets <see cref="IList{T}"/> containing all <see cref="ValidationResult"/> for <see cref="Rule"/>s that have failed validation.
			/// </summary>
			public virtual IList<ValidationResult> ValidatorResultsInError
			{
				get
				{
					return propertyValidationManager.ValidatorResultsInError;
				}
			}


			/// <summary>
			/// Gets a <see see="ICollection"/> of <see langword="string"/>s that contain all 
			/// the <see cref="ValidationResult.ErrorMessage"/>s for all the 
			/// <see cref="ValidationResult"/>s in <see cref="ValidatorResultsInError"/>.
			/// </summary>
			public virtual IList<string> ErrorMessages
			{
				get
				{
					return ResultFormatter.GetErrorMessages(propertyValidationManager.ValidatorResultsInError);
				}
			}


			[RequiredIntRule]
			public int Age
			{
				get;
				set;
			}

			#endregion

			#region Methods

			/// <summary>
			/// Gets a <see lanword="bool"/> indicating if the current state is valid.
			/// </summary>
			public bool Validate()
			{
				//Base behavior is to perform validations and return boolean value.
				//Sub-class can override this if, for example, they are validating on the fly.
				propertyValidationManager.ValidateAll();
				return propertyValidationManager.IsValid;
			}
			#endregion
		}

		[TestFixture]
		public class ExampleUsage
		{
			[Test]
			public void RunIsValid()
			{
				var person = new Person();

				// Initially not valid
				Assert.IsFalse(person.Validate());

				// Set Age
				person.Age = 10;

				// It is now valid
				Assert.IsTrue(person.Validate());
			}



			[Test]
			public void RunValidatorResultsInError()
			{
				var person = new Person();
				Assert.IsFalse(person.Validate());
				// Initially there will be 1 item in ValidatorResultsInError.
				Assert.AreEqual(1, person.ValidatorResultsInError.Count);

				// Set Age
				person.Age = 10;

				// Since Validate has not been called the count will not have changed
				Assert.AreEqual(1, person.ValidatorResultsInError.Count);

				Assert.IsTrue(person.Validate());
				// Since Validate has now been called the count will have changed
				Assert.AreEqual(0, person.ValidatorResultsInError.Count);
			}


		}
		#endregion
	}
}